// 任意整数除以三求商和余数
module top #(parameter DATAWIDTH = 16)(
           input clk,
           input rst_n,
           input vld_in,
           input [DATAWIDTH - 1: 0] data_in,
           output reg [DATAWIDTH - 1: 0] quotient,
           output reg [1: 0] reminder,
           output reg vld_out
       );

reg [1: 0] current_state;
reg [1: 0] next_state;
reg [$clog2(DATAWIDTH): 0] cnt;
reg [DATAWIDTH - 1: 0] data_reg;

parameter idle = 2'b11;

always@(posedge clk or negedge rst_n)
	begin
		if (!rst_n)
			current_state <= idle;
		else
			current_state <= next_state;
	end
always@( * )
	begin
		if (!rst_n)
			next_state = idle;
		else
			begin
				case (current_state)
					idle:
						next_state = vld_in ? 2'b00 : idle;
					2'b00:
						begin
							if (cnt == DATAWIDTH)
								next_state = idle;
							else if (data_reg[DATAWIDTH - 1])
								next_state = 2'b01;
							else
								next_state = 2'b00;
						end
					2'b01:
						begin
							if (cnt == DATAWIDTH)
								next_state = idle;
							else if (data_reg[DATAWIDTH - 1])
								next_state = 2'b00;
							else
								next_state = 2'b10;
						end
					2'b10:
						begin
							if (cnt == DATAWIDTH)
								next_state = idle;
							else if (data_reg[DATAWIDTH - 1])
								next_state = 2'b10;
							else
								next_state = 2'b01;
						end
					default:
						next_state = idle;
				endcase
			end
	end


always @(posedge clk or negedge rst_n)
	if (!rst_n)
		begin
			{cnt, data_reg, reminder, quotient, vld_out} <= 0;
		end
	else
		begin
			case (current_state)
				idle:
					begin
						{vld_out, cnt} <= 0;
						if (vld_in)
							data_reg <= data_in;
						else
							data_reg <= data_reg;
					end
				2'b00, 2'b01, 2'b10:
					begin
						if (cnt == DATAWIDTH - 1)
							begin
								cnt <= cnt + 1;        // without this,remainder will be next_state=IDLE=2'b11'
								reminder <= next_state;
								vld_out <= 1;
							end
						else
							begin
								cnt <= cnt + 1;
								vld_out <= 0;
								data_reg <= {data_reg[DATAWIDTH - 2: 0], 1'b0};
							end
						if (data_reg[DATAWIDTH - 1])
							quotient <= {quotient[DATAWIDTH - 2: 0], current_state[1] | current_state[0]};
						else
							quotient <= {quotient[DATAWIDTH - 2: 0], current_state[1]};
					end
			endcase
		end
endmodule
